package org.hiucung.desktoptranslationtools.utils

import org.dom4j.Document
import org.dom4j.Element
import org.dom4j.io.SAXReader
import org.hiucung.desktoptranslationtools.bean.RowResult
import org.hiucung.desktoptranslationtools.bean.Translation
import java.io.File
import kotlin.collections.iterator

/**
 * @title: GradleTranslationHelper
 * @projectName DesktopTranslationTools
 * @description: settings.gradle文件收集模块并获取各个模块的翻译 xml
 * @author Kicc
 * @date 2025/7/22 13:41
 */
object GradleTranslationHelper {

    /**
     * 从项目的 `settings.gradle` 文件中提取所有声明的 Gradle 模块名称。
     * @param root 项目的根目录（包含 `settings.gradle` 的目录）
     * @return 模块名称列表（如 `["app", "library"]`），如果文件不存在或未声明模块则返回空列表
     */
    fun extractGradleModuleNames(root: File): List<String> {
        // 1. 在根目录下查找 `settings.gradle` 文件（可能存在多个，取最后一个匹配项）
        val settingGradleFile = root.listFiles().findLast { it.name == "settings.gradle" }

        // 2. 定义正则表达式，匹配 `:moduleName` 格式的模块声明（如 `:app`）
        val moduleNameRegex = Regex(":(\\w+)")

        // 3. 存储提取到的模块名
        val moduleConfigName = mutableListOf<String>()

        // 4. 如果文件存在，逐行读取内容
        val lines = settingGradleFile?.readLines()
        lines?.forEach { line ->
            // 5. 跳过注释行（包含 `//`），仅处理包含 `include` 的行
            if (!line.contains("//") && line.contains("include")) {
                // 6. 使用正则匹配模块名，去掉开头的 `:` 后存入列表
                moduleNameRegex.find(line)?.value?.replace(":", "")?.run {
                    moduleConfigName.add(this)
                }
            }
        }

        // 7. 返回模块名列表
        return moduleConfigName
    }

    // values-ar values-de values-es ...
    fun collectTranslationsFromRes(
        moduleName: String,
        srcDir: File
    ): List<Translation> {//读取module的资源
        val codeRegex = "values-(.*)".toRegex()
        val translationLocals = mutableListOf<Translation>()

        // 获取项目里 res的 File，遍历所有文件夹，过滤出 values开头的文件夹
        val resFile = File(srcDir, "src/main/res")
        resFile.listFiles { dir ->
            dir.isDirectory && dir.name.startsWith("values")
        }?.forEach { file ->
            // 如果是默认的 values 目录，标记为 "default"
            // 否则使用正则提取语言代码（如 values-es 提取出 es）
            val languageCode = if (file.name == "values") {
                "default"
            } else {
                codeRegex.find(file.name)?.groupValues?.get(1)
            } ?: "default"

            // 获取如 values-es目录里面的 xml文件，判断之后进行 xml解析，返回 TranslationBean
            file.listFiles()?.forEach { valueFile ->
                if (valueFile.isFile) {
                    val fileDesc = valueFile.name.split(".")
                    val fileSuffix = fileDesc.last()
                    if (fileSuffix == "xml") {
                        val temp = readXml(moduleName, languageCode, valueFile)
                        if (temp.isNotEmpty()) {
                            translationLocals.addAll(temp)
                        }
                    }
                }
            }
        }
        return translationLocals
    }

    fun readXml(moduleName: String, localCode: String, file: File): List<Translation> {
        val xmlFile = SAXReader().read(file)
        val translations = mutableListOf<Translation>()

        // 解析 string标签
        translations.addAll(parseStringElements(xmlFile, moduleName, localCode))

        // 解析 stringArray标签
        if (file.name.equals("strings.xml", ignoreCase = true)) {
            translations.addAll(parseStringArrays(xmlFile, moduleName, localCode))
        }

        return translations
    }

    private fun parseStringElements(xmlFile: Document, moduleName: String, localCode: String): List<Translation> {
        return xmlFile.selectNodes("//string")?.mapNotNull { node ->
            (node as? Element)?.let { element ->
                createTranslationBean(
                    localCode,
                    moduleName,
                    element.attribute("name")?.text ?: return@mapNotNull null,
                    element.text,
                    element.attribute("translatable")?.text == "false"
                )
            }
        } ?: emptyList()
    }

    private fun parseStringArrays(xmlFile: Document, moduleName: String, localCode: String): List<Translation> {
        return xmlFile.selectNodes("//string-array")?.flatMap { node ->
            (node as? Element)?.let { arrayElement ->
                val arrayName = arrayElement.attributeValue("name") ?: return@flatMap emptyList()
                val noTranslation = arrayElement.attribute("translatable")?.text == "false"

                arrayElement.elements("item")?.mapIndexed { index, item ->
                    createTranslationBean(
                        localCode,
                        moduleName,
                        "$arrayName/@$index",
                        item.text,
                        noTranslation
                    )
                } ?: emptyList()
            } ?: emptyList()
        } ?: emptyList()
    }

    private fun createTranslationBean(
        languageCode: String,
        moduleName: String,
        key: String,
        value: String,
        noTranslation: Boolean
    ): Translation {
        return Translation(
            languageCode = languageCode,
            moduleName = moduleName,
            key = key,
            value = value,
            // 可能关联了其它的字符串比如： <string name="home" translatable="false">@string/main</string>
            isStringReference = value.startsWith("@string/"),
            isTranslatable = noTranslation
        )
    }

    fun processTranslationsByModule(
        translations: List<Translation>,
        exportNoTranslation: Boolean = false
    ): List<RowResult> {

        // 过滤出所有翻译中所属模块名
        val moduleSet = translations.map { it.moduleName }.toSet()

        // 根据模块名，把翻译归类到所属模块
        val modulesTranslations = mutableListOf<List<Translation>>()
        moduleSet.forEach { module ->
            modulesTranslations.add(translations.filter { it.moduleName == module })
        }

        val rowResults = mutableListOf<RowResult>()

        modulesTranslations.forEach { module ->
            // 按照 key再进行分组，拿到同一个 name和不同的 value集合，也就是多国语言翻译
            val translationMap = module.groupBy { it.key }
            for ((key, value) in translationMap) {
                if (exportNoTranslation && translationMap[key]?.find { it.isTranslatable } != null) {
                    continue //不进行解析,跳过
                }
                if (translationMap[key]?.find { it.isStringReference } != null) {
                    continue //不做解析,跳过
                }
                // 拿到不同地域对应的翻译 map
                val languageToValueMap = value.associate { Pair(it.languageCode, it.value) }
                // 默认取英语的长度作为翻译的最大长度
                val maxLength = languageToValueMap["en"]?.length
                    ?: languageToValueMap["default"]?.length
                    ?: languageToValueMap.values.firstOrNull()?.length
                    ?: 0

                rowResults.add(
                    RowResult(
                        value[0].moduleName,
                        maxLength,
                        key,
                        languageToValueMap
                    )
                )
            }
        }
        return rowResults
    }
}